#ifndef _KLAS_SCENE_HPP_
#define _KLAS_SCENE_HPP_

#include "../include/Rectangle.hpp"
#include "../include/Vector2.hpp"
#include "../include/Node.hpp"
#include <vector>
#include <list>
using namespace std;


namespace klas
{
  
	//! The scene is a group of nodes.
	class Scene
	{
		public:
			
			//! Ctor.  Creates the scene.
			/*! \param dim The dimensions of the scene.
					\param cellSize The side length of each cell inside the scene (pixels) */
			Scene(const Vector2<Real>& dim, Real cellSize=1000);
			
			//! Removes and deletes all nodes in the scene.
			void kill();
			
			//! Adds the node to the scene.
			/*! \param node The node to add to the scene.
					\param flags Additional flags when adding the node to the scene.  See FLAGS
					\return The node added to the scene. */
			Node* add(Node* node, uint8 flags=0x00);
			
			//! Updates the node in the scene.
			/*! \param node The node to update.
					\return True if the node switched cells, otherwise false. */
			bool update(Node* node);
			
			//! Returns a given node.
			/*! \param ID The ID of the node to return.
					\return Returns the node with the specified ID.  On error, returns (Node*)0 */
			Node* get(Real ID);			
			
			//! Returns a list of nodes either inside or intersecting with the rectangle.
			/*! \param rect The rectangle to find nodes inside of.
					\return A list of nodes that are intersecting with the rectangle. */
			list<Node*> getIntersectingNodes(const Rectangle<Real>& rect);
			
			//! Render's the scene.
			/*! This is accomplished by calling getIntersectingNodes and then calling
					their 'render' functions. */
			void render(const Rectangle<Real>& screen);
			
			//! Renders fonts
			void renderFonts();
			
			//! Possible flags to use when adding nodes.
			enum FLAGS {
					DEEP_COPY = 0x01, //! Makes a deep copy of the node.
					RENDER_BACK = 0x02 //! The node will be placed behind pre-existing objects.
			};
			
			//! Updates collision states.
			/*! This function must be called whenever nodes move positions to ensure
			    accurate data. */
			void updateCollisionState();
			
			//! Checks to see if node a and b are colliding.
			/*! \param a A node to check.
			    \param b The node to check against a.
			    \return True if the nodes are colliding, else false. */
			bool isCollidingWith(Node* a, Node* b);
			
			//! Gets a list of nodes that node is colliding with.
			/*! \param node The node to check for collisions with.
			    \return A list of nodes that the node is colliding with. */
			list<Node*> collidingWith(Node* node);
			
			
			//! Removes a node from the scene, and does NOT delete it. */
			/*! \param node The node to remove.
			    \return True for a successful removal, false for failure. */
			bool remove(Node* node);
			
		private:
			
			//! The cell is used to group nodes together, into a larger clump.
			struct Cell
			{
				Rectangle<Real> rect;
				list<Node*> members;
				
				Cell(const Rectangle<Real>& rect);
			};
			
			//! The side length of each cell, in pixels.
			Real m_cellSize,
			
			//! The next available ID.
					 m_nextID;
			
			//! The dimensions of the scene, in pixels.
			Vector2<Real> m_dimensions,
			
			//! A convience variable that contains the number of cells in each side.
							m_numCells;
			
			//! The cells in the scene.  These cells clump nodes together.
			vector<Cell> m_cells;
			
			//! Our list of font nodes, to be rendered last.
			list<Node*> m_fontNodes;
			
			//! Takes a position and returns the index of which cell it is in.
			/*! \param pos The position to find the index of.
					\return The cell index. */
			iReal posToIdx(const Vector2<Real>& pos);
	};
}

#endif
